classdef BinaryRelevance ...
        < MultiLabelAlgorithm ...
        & BinaryClassAlgorithm0able ...
        & ZAlgorithmable ...
        & MultiLabelMetricable
    %BINARYRELEVANCE Summary of this class goes here
    %   Detailed explanation goes here
    
    properties ( SetAccess = protected )
    end
    
    methods
        function [ this ] = BinaryRelevance( name, algorithm0 )
            if nargin == 0
                this.setName('br');
            end
            if nargin >= 1
                this.setName(name);
            end
            if nargin >= 2
                this.setAlgorithm0(algorithm0);
            end
        end
    end
    
    methods
        function [  ] = build( this, X1, Y1 )
            %BUILD build `@BinaryRelevance` model
            % BinaryRelevance::build( this:BinaryRelevance,
            %                         X1:double,
            %                         Y1:double )
            %                >>     [  ]
            
            nLab = size(Y1, 2);
            this.zAlgorithm = cell(1, nLab);
            
            for iLab = 1:nLab
                this.zAlgorithm{iLab} = this.algorithm0.clone();
                this.zAlgorithm{iLab}.build(X1, Y1(:, iLab));
            end
        end
        
        function [ result ] = apply( this, X2, Y2 )
            %APPLY Apply `@BinaryRelevance` model
            % BinaryRelevance::build( this:BinaryRelevance,
            %                         X2:double
            %                         Y2:double
            %                >>     [ result.Y_hat,
            %                         result.Y_out ]
            
            nLab = length(this.zAlgorithm);
            assert(nLab == size(Y2, 2));
            
            result.Y_hat = nan(size(Y2));
            result.Y_out = result.Y_hat;
            
            for iLab = 1:nLab
                result_i = this.zAlgorithm{iLab}.apply(X2, Y2(:, iLab));
                result.Y_hat(:, iLab) = result_i.Y_hat;
                result.Y_out(:, iLab) = result_i.Y_out;
            end
        end
    end
    
end

